﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace K9Nano.Share.Extensions
{
    public static class StringExtensions
    {
        public static string ToSnakeCase(this string camelCase)
        {
            var sb = new StringBuilder();
            sb.Append(char.ToLower(camelCase[0]));
            for (var i = 1; i < camelCase.Length; i++)
            {
                if (char.IsUpper(camelCase[i]))
                {
                    sb.Append("_" + char.ToLower(camelCase[i]));
                }
                else
                {
                    sb.Append(camelCase[i]);
                }
            }
            return sb.ToString();
        }

        public static string EnsureNotEndWith(this string raw, char c, bool ignoreCase = true)
        {
            if (raw[^1] == c || ignoreCase && raw[^1] == char.ToUpper(c))
            {
                return raw.Remove(raw.Length - 1);
            }
            return raw;
        }

        /// <summary>
        /// 单词变成单数形式
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        public static string ToSingular(this string word)
        {
            var regs = new[]
            {
                new KeyValuePair<string, string>("${keep}y", "(?<keep>[^aeiou])ies$"),
                new KeyValuePair<string, string>("${keep}", "(?<keep>[aeiou]y)s$"),
                new KeyValuePair<string, string>("${keep}", "(?<keep>[sxzh])es$"),
                new KeyValuePair<string, string>("${keep}", "(?<keep>[^sxzhyu])s$")
            };

            foreach (var r in regs)
            {
                var regex = new Regex(r.Value);
                if (regex.IsMatch(word))
                {
                    return regex.Replace(word, r.Key);
                }
            }

            return word;
        }
        /// <summary>
        /// 单词变成复数形式
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        public static string ToPlural(this string word)
        {
            var regs = new[]
            {
                new KeyValuePair<string, string>("${keep}ies", "(?<keep>[^aeiou])y$"),
                new KeyValuePair<string, string>("${keep}s", "(?<keep>[aeiou]y)$"),
                new KeyValuePair<string, string>("${keep}es", "(?<keep>[sxzh])$"),
                new KeyValuePair<string, string>("${keep}s", "(?<keep>[^sxzhy])$")
            };

            foreach (var r in regs)
            {
                Regex.Replace(word, r.Value, r.Key);
            }

            return word;
        }

        public static string F(this string template, params object[] args)
        {
            return string.Format(template, args);
        }

        public static string RemovePreFix(this string str, params string[] preFixes)
        {
            if (str == null)
            {
                return null;
            }

            if (str == string.Empty)
            {
                return string.Empty;
            }

            if (preFixes.IsNullOrEmpty())
            {
                return str;
            }

            foreach (var preFix in preFixes)
            {
                if (str.StartsWith(preFix))
                {
                    return str.Right(str.Length - preFix.Length);
                }
            }

            return str;
        }

        public static string Right(this string str, int len)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }

            if (str.Length < len)
            {
                throw new ArgumentException("len argument can not be bigger than given string's length!");
            }

            return str.Substring(str.Length - len, len);
        }

        public static string Left(this string str, int len)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }

            if (str.Length < len)
            {
                throw new ArgumentException("len argument can not be bigger than given string's length!");
            }

            return str.Substring(0, len);
        }

        public static string RemovePostFix(this string str, params string[] postFixes)
        {
            if (str == null)
            {
                return null;
            }

            if (str == string.Empty)
            {
                return string.Empty;
            }

            if (postFixes.IsNullOrEmpty())
            {
                return str;
            }

            foreach (var postFix in postFixes)
            {
                if (str.EndsWith(postFix))
                {
                    return str.Left(str.Length - postFix.Length);
                }
            }

            return str;
        }

        /// <summary>
        /// 简单模式匹配
        /// </summary>
        /// <param name="value"></param>
        /// <param name="pattern">支持a*,  *a, a*b</param>
        /// <returns></returns>
        public static bool WildcardMatch(this string value, string pattern, char wildcard = '*')
        {
            if (value == null || pattern == null) return false;

            var parts = pattern.Split(new[] { wildcard }, StringSplitOptions.RemoveEmptyEntries);
            var tocheck = value;
            var start = 0;
            var end = parts.Length;

            if (!pattern.StartsWith(wildcard.ToString(CultureInfo.InvariantCulture)))
            {
                if (!tocheck.StartsWith(parts.First()))
                    return false;

                start = 1;
            }

            if (!pattern.EndsWith(wildcard.ToString(CultureInfo.InvariantCulture)))
            {
                if (!tocheck.EndsWith(parts.Last()))
                    return false;

                end--;
            }

            for (var i = start; i < end; i++)
            {
                var index = tocheck.IndexOf(parts[i], StringComparison.Ordinal);
                if (index < 0)
                    return false;

                tocheck = tocheck.Substring(index);
            }

            return true;
        }
    }
}